package com.kk.nio.work01.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import com.kk.nio.work01.server.channeldata.ChannelDataProcess;
import com.kk.util.NumberSeq;

/**
 * 文件选择器用来处理具体的文件操作请求
* 源文件名：FileSelect.java
* 文件版本：1.0.0
* 创建作者：liujun
* 创建日期：2016年11月4日
* 修改作者：liujun
* 修改日期：2016年11月4日
* 文件描述：liujun
* 版权所有：Copyright 2016 zjhz, Inc. All Rights Reserved.
*/
public class MultServerFileSelect implements Runnable {

    /**
     * 具体的select选择器对象
    * @字段说明 select
    */
    private final Selector select;

    /**
     * 服务器操作通道
    * @字段说明 serverSocketChan
    */
    private final ServerSocketChannel serverSocketChan;

    /**
     * 是否运行的标识
    * @字段说明 runFlag
    */
    private volatile boolean runFlag = true;

    /**
     * 读取通道操作
    * @字段说明 readChannel
    */
    private ChannelDataProcess readChannel = new ChannelDataProcess();

    public MultServerFileSelect(int port) throws IOException {
        // 打开服务器socketserver通道，并绑定地址
        this.serverSocketChan = ServerSocketChannel.open();
        this.serverSocketChan.bind(new InetSocketAddress("localhost", port));
        // 设置为非阻塞模式
        this.serverSocketChan.configureBlocking(false);
        // 创建 多路复用器
        this.select = Selector.open();
        // 首先注册通道的连接事情
        this.serverSocketChan.register(select, SelectionKey.OP_ACCEPT);

    }

    @Override
    public void run() {
        while (runFlag) {
            try {
                // 第一秒进行一次的唤醒
                this.select.select(1000);

                // 轮论已经注册的事情进行遍历
                Set<SelectionKey> setKeys = this.select.selectedKeys();

                Iterator<SelectionKey> setIterKey = setKeys.iterator();

                while (setIterKey.hasNext()) {
                    // 处理事件
                    SelectionKey key = setIterKey.next();

                    try {
                        this.handler(key);
                    } catch (IOException e) {
                        e.printStackTrace();
                        // 将事件取消
                        key.cancel();
                    }
                    // 需在将当前已经激活的事情进行移除
                    setIterKey.remove();

                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void handler(SelectionKey key) throws IOException {
        // 如果是连接事情，将改为连接事情
        if (key.isValid()) {
            // 套接字已经准备完毕
            if (key.isAcceptable()) {
                ServerSocketChannel severChanner = (ServerSocketChannel) key.channel();

                SocketChannel clientChannel = severChanner.accept();

                clientChannel.configureBlocking(false);

                // 为每个连接通道附加一个id

                // 将通道交通读取流事情去处理
                clientChannel.register(select, SelectionKey.OP_READ, NumberSeq.getnewInstance().nextSeqValue());
            } else if (key.isReadable()) {
                // 得到文件通道，将数据进行接收
                SocketChannel channel = (SocketChannel) key.channel();

                int id = (int) key.attachment();

                // 将通道交通读取类处理
                readChannel.addReadChannel(id, channel);

            } else if (key.isWritable()) {

                // 得到文件通道，将数据进行接收
                SocketChannel channel = (SocketChannel) key.channel();

                // 得到文件通道进行输数据回写响应
                channel.register(select, SelectionKey.OP_WRITE);
            }
        }
    }
}
